package generator

import (
	"fmt"
	"os"
	"reflect"
	"strings"
	"time"
)

// TypeScriptGenerator TypeScript 类型生成器
type TypeScriptGenerator struct {
	outputDir string
}

// NewTypeScriptGenerator 创建生成器
func NewTypeScriptGenerator(outputDir string) *TypeScriptGenerator {
	return &TypeScriptGenerator{
		outputDir: outputDir,
	}
}

// Generate 生成 TypeScript 类型文件
func (g *TypeScriptGenerator) Generate(models map[string]interface{}) error {
	// 确保输出目录存在
	if err := os.MkdirAll(g.outputDir, 0755); err != nil {
		return fmt.Errorf("创建输出目录失败: %w", err)
	}

	for name, model := range models {
		content := g.generateInterface(name, model)
		filename := fmt.Sprintf("%s/%s.types.ts", g.outputDir, strings.ToLower(name))

		if err := os.WriteFile(filename, []byte(content), 0644); err != nil {
			return fmt.Errorf("写入文件失败: %w", err)
		}
	}

	return nil
}

// generateInterface 生成接口定义
func (g *TypeScriptGenerator) generateInterface(name string, model interface{}) string {
	var sb strings.Builder

	// 文件头注释
	sb.WriteString("/**\n")
	sb.WriteString(fmt.Sprintf(" * %s 相关类型定义\n", name))
	sb.WriteString(" * 此文件由后端自动生成，请勿手动修改\n")
	sb.WriteString(fmt.Sprintf(" * 生成时间：%s\n", time.Now().Format("2006-01-02 15:04:05")))
	sb.WriteString(" */\n\n")

	// 导入公共类型
	sb.WriteString("import type { PageParams, PageResult } from './common.types'\n\n")

	// 生成接口
	sb.WriteString(fmt.Sprintf("export interface %s {\n", name))

	t := reflect.TypeOf(model)
	if t.Kind() == reflect.Ptr {
		t = t.Elem()
	}

	for i := 0; i < t.NumField(); i++ {
		field := t.Field(i)
		jsonTag := field.Tag.Get("json")
		if jsonTag == "" || jsonTag == "-" {
			continue
		}

		// 提取字段名
		fieldName := strings.Split(jsonTag, ",")[0]

		// 生成字段注释
		if comment := field.Tag.Get("comment"); comment != "" {
			sb.WriteString(fmt.Sprintf("  /** %s */\n", comment))
		}

		// 生成字段定义
		tsType := g.goTypeToTS(field.Type)
		optional := ""
		if strings.Contains(jsonTag, "omitempty") || field.Type.Kind() == reflect.Ptr {
			optional = "?"
		}

		sb.WriteString(fmt.Sprintf("  %s%s: %s\n", fieldName, optional, tsType))
	}

	sb.WriteString("}\n")

	return sb.String()
}

// goTypeToTS Go 类型转 TypeScript 类型
func (g *TypeScriptGenerator) goTypeToTS(t reflect.Type) string {
	// 处理指针类型
	if t.Kind() == reflect.Ptr {
		return g.goTypeToTS(t.Elem()) + " | null"
	}

	// 处理切片
	if t.Kind() == reflect.Slice {
		return g.goTypeToTS(t.Elem()) + "[]"
	}

	// 处理 map
	if t.Kind() == reflect.Map {
		keyType := g.goTypeToTS(t.Key())
		valueType := g.goTypeToTS(t.Elem())
		return fmt.Sprintf("Record<%s, %s>", keyType, valueType)
	}

	// 基本类型映射
	switch t.Kind() {
	case reflect.String:
		return "string"
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
		reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
		reflect.Float32, reflect.Float64:
		return "number"
	case reflect.Bool:
		return "boolean"
	case reflect.Struct:
		// time.Time 特殊处理
		if t.String() == "time.Time" {
			return "string"
		}
		// 其他结构体使用类型名
		return t.Name()
	default:
		return "any"
	}
}

// GenerateAPIDoc 生成 API 文档（Markdown 格式）
func GenerateAPIDoc(apis []APIInfo, outputPath string) error {
	var sb strings.Builder

	sb.WriteString("# API 接口文档\n\n")
	sb.WriteString(fmt.Sprintf("生成时间：%s\n\n", time.Now().Format("2006-01-02 15:04:05")))

	for _, api := range apis {
		sb.WriteString(fmt.Sprintf("## %s\n\n", api.Summary))
		sb.WriteString(fmt.Sprintf("**描述**: %s\n\n", api.Description))
		sb.WriteString(fmt.Sprintf("**方法**: `%s`\n\n", api.Method))
		sb.WriteString(fmt.Sprintf("**路径**: `%s`\n\n", api.Path))

		if api.Auth {
			sb.WriteString("**需要认证**: 是\n\n")
		}

		if api.Permission != "" {
			sb.WriteString(fmt.Sprintf("**需要权限**: `%s`\n\n", api.Permission))
		}

		// 请求参数
		if len(api.Params) > 0 {
			sb.WriteString("### 请求参数\n\n")
			sb.WriteString("| 参数名 | 类型 | 必填 | 说明 |\n")
			sb.WriteString("| ------ | ---- | ---- | ---- |\n")
			for _, param := range api.Params {
				required := "否"
				if param.Required {
					required = "是"
				}
				sb.WriteString(fmt.Sprintf("| %s | %s | %s | %s |\n",
					param.Name, param.Type, required, param.Description))
			}
			sb.WriteString("\n")
		}

		// 响应示例
		if api.Response != "" {
			sb.WriteString("### 响应示例\n\n")
			sb.WriteString("```json\n")
			sb.WriteString(api.Response)
			sb.WriteString("\n```\n\n")
		}

		sb.WriteString("---\n\n")
	}

	return os.WriteFile(outputPath, []byte(sb.String()), 0644)
}

// APIInfo API 信息
type APIInfo struct {
	Summary     string
	Description string
	Method      string
	Path        string
	Auth        bool
	Permission  string
	Params      []ParamInfo
	Response    string
}

// ParamInfo 参数信息
type ParamInfo struct {
	Name        string
	Type        string
	Required    bool
	Description string
}
